package com.vcredit.creditcat.service.product;

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.vcredit.bird.vo.product.kak.CreditKakAmountParamDto;
import com.vcredit.bird.vo.product.kak.CreditKakAuditParamDto;
import com.vcredit.bird.vo.product.kak.CreditKakDecisionResult;
import com.vcredit.bird.vo.product.kak.CreditKakParamDto;
import com.vcredit.creditcat.enumtype.AuthItemEnum;
import com.vcredit.creditcat.enumtype.MerchantProductEnum;
import com.vcredit.creditcat.exception.ProductCanNotApplyException;
import com.vcredit.creditcat.exception.ResourceException;
import com.vcredit.creditcat.model.Cust;
import com.vcredit.creditcat.model.CustProductApply;
import com.vcredit.creditcat.model.ProductItem;
import com.vcredit.creditcat.service.CustProductApplyService;
import com.vcredit.creditcat.service.product.enumtype.CreditSourceTypeEnum;
import com.vcredit.creditcat.service.product.enumtype.KakAuditResultEnum;
import com.vcredit.creditcat.service.product.enumtype.KakCityCodeEnum;
import com.vcredit.creditcat.service.product.enumtype.KakIsGJJEnum;
import com.vcredit.creditcat.service.product.enumtype.ProductEnumType;
import com.vcredit.creditcat.service.product.util.EnumExtUtil;
import com.vcredit.creditcat.util.ConcurrentDateUtil;
import com.vcredit.creditcat.util.Constants;
import com.vcredit.creditcat.util.Utility;
import com.vcredit.creditcat.vo.CommonResultExt;
import com.vcredit.framework.annotation.Log;
import com.vcredit.framework.util.BeanUtil;
import com.vcredit.framework.util.JacksonUtil;

/**
 * @author 张新功
 */
@Service("creditKak")
public class CreditKakaDaiApplyService implements IProductApplyService {
  @Autowired
  private CustProductApplyService custProductApplyService;
  @Autowired
  @Qualifier("productStrategyContext")
  private ICreditCommonService creditCommonApplyService;

  @Log
  @Override
  public Object applyCommit(Long custId, Long productId,Map<String,String> otherParams) throws Exception {
    Object prepareProductApplyParamDto =
        creditCommonApplyService.prepareProductApplyUserInfo(custId, productId,
            MerchantProductEnum.creditKak,otherParams);
    if (prepareProductApplyParamDto instanceof HashMap) {
      @SuppressWarnings("unchecked")
      Map<String, Object> resultMap = (Map<String, Object>) prepareProductApplyParamDto;

      if (resultMap.containsKey("commitError")) {//提交接口业务异常

        creditCommonApplyService.saveCustProductApply(this.getSaveAuditResultParam(custId,
            productId, resultMap.get("commitError")));
        return null;//返回
      }

      if (resultMap.containsKey("expiredList")) {
        //返回给前端 过期的信用项
        return resultMap.get("expiredList");
      }
    }

    if (null == prepareProductApplyParamDto) {
      return null;
    }

    creditCommonApplyService.saveCustProductApply(this.getSaveAuditResultParam(custId, productId,
        null));

    Object auditResult =
        creditCommonApplyService.getAuditResult(prepareProductApplyParamDto,
            MerchantProductEnum.creditKak);

    creditCommonApplyService.saveCustProductApply(getSaveAuditResultParam(custId, productId,
        auditResult));
    return null;
  }


  @Log
  @Override
  public void queryLimit(CustProductApply custProductApply) throws Exception {
    CustProductApply creditAmoutResult =
        creditCommonApplyService.getCreditAmoutResult(custProductApply,
            MerchantProductEnum.creditKak);
    if (null == creditAmoutResult) {
      return;
    }
    creditCommonApplyService.saveCustProductApply(creditAmoutResult);
  }


  /** 
   * TODO 简单描述该方法的实现功能（可选）. 
   * @throws IOException 
   * @throws JsonMappingException 
   * @throws JsonParseException 
   * @see com.vcredit.creditcat.service.product.IProductApplyService#hasAlreadyAuditAmount(com.vcredit.bird.vo.product.ProductOutputDto) 
   */
  @Override
  public Boolean hasAlreadyAuditAmount(Object object) throws ProductCanNotApplyException,
      JsonParseException, JsonMappingException, IOException {
    Boolean hasAmout = false;
    return hasAmout;
  }

  /** 
   * TODO 简单描述该方法的实现功能（可选）. 
   * @throws ResourceException 
   * @see com.vcredit.creditcat.service.product.IProductApplyService#getProductCommitParam(com.vcredit.bird.vo.product.CreditApplyParamDto) 
   */
  @Log
  @Override
  public Object getProductCommitParam(Long productId, Cust cust, Map<AuthItemEnum, Object> itemMap,Map<String,String> otherParams)
      throws ResourceException, IllegalArgumentException, Exception {
    CreditKakParamDto kakaCommitDto = new CreditKakParamDto();
    BeanUtil.copy(cust, kakaCommitDto);
    for (Entry<AuthItemEnum, Object> entrySet : itemMap.entrySet()) {
      BeanUtil.copy(entrySet.getValue(), kakaCommitDto);
    }
    String salaryKey =
        creditCommonApplyService.getProductEnumCode(productId,
            ProductEnumType.monthlyIncome.getCode(), kakaCommitDto.getSalaryKey());
    String educationKey =
        creditCommonApplyService.getProductEnumCode(productId, ProductEnumType.education.getCode(),
            kakaCommitDto.getEducationKey());
    String marriageKey =
        creditCommonApplyService.getProductEnumCode(productId, ProductEnumType.marriage.getCode(),
            kakaCommitDto.getMarriageKey());
    KakIsGJJEnum isGJJEnum =
        EnumExtUtil.getEnumOnValue(KakIsGJJEnum.class,
            String.valueOf(kakaCommitDto.getHasAccumulation()), "code");
    KakCityCodeEnum cityCodeEnum = KakCityCodeEnum.valueOf(kakaCommitDto.getCityName());
    kakaCommitDto.setSalaryValue(salaryKey);
    kakaCommitDto.setEducationValue(educationKey);
    kakaCommitDto.setMarriageValue(marriageKey);
    kakaCommitDto.setHasAccumulationValue(isGJJEnum.getDesc());
    kakaCommitDto.setCityName(String.valueOf(cityCodeEnum.getCode()));
    //转成base64
    kakaCommitDto.setIdFront(creditCommonApplyService.getBase64StringByCode(kakaCommitDto
        .getIdFront()));
    kakaCommitDto.setIdBack(creditCommonApplyService.getBase64StringByCode(kakaCommitDto
        .getIdBack()));
    kakaCommitDto.setIdHandheld(creditCommonApplyService.getBase64StringByCode(kakaCommitDto
        .getIdHandheld()));
    kakaCommitDto.setAccount(Constants.KAK_SUBMIT_ACCOUNT);
    kakaCommitDto.setUserId(Constants.PROJECT_PREFIX.concat(String.valueOf(kakaCommitDto
        .getCustId())));
    kakaCommitDto.setCreditSourceType(CreditSourceTypeEnum.shanghai.getKey());
    return kakaCommitDto;
  }

  /** 
   * TODO 简单描述该方法的实现功能（可选）. 
   * @throws Exception 
   * @see com.vcredit.creditcat.service.product.IProductApplyService#getCreditAmountParam() 
   */
  @Log
  @Override
  public Object getCreditAmountParam(Cust cust, ProductItem productItem) throws Exception {
    CreditKakAuditParamDto auditDto = new CreditKakAuditParamDto();
    Map<String, Object> resultMap =
        creditCommonApplyService.getAuthMap(cust, cust.getLastProccessId(),
            productItem.getMinCode());
    if (resultMap.containsKey("expiredList")) {
      //返回给前端 过期的信用项
      return null;
    }
    @SuppressWarnings("unchecked")
    Map<AuthItemEnum, Object> autMap = (Map<AuthItemEnum, Object>) resultMap.get("authMap");
    for (Entry<AuthItemEnum, Object> entrySet : autMap.entrySet()) {
      BeanUtil.copy(entrySet.getValue(), auditDto);
    }
    auditDto.setAccount(Constants.KAK_SUBMIT_ACCOUNT);
    auditDto.setUserId(Constants.PROJECT_PREFIX.concat(String.valueOf(cust.getCustId())));
    auditDto.setCreditSourceType(CreditSourceTypeEnum.shanghai.getKey());
    return auditDto;
  }

  /** 
   * TODO 简单描述该方法的实现功能（可选）. 
   * @throws ProductCanNotApplyException 
   * @see com.vcredit.creditcat.service.product.IProductApplyService#getAudInputParam() 
   */
  @Log
  @Override
  public Object getAudInputParam(Object outputDto) throws ProductCanNotApplyException {
    return null;
  }

  @Log
  @Override
  public CustProductApply getSaveAuditResultParam(Long custId, Long productId, Object input)
      throws Exception {
    CustProductApply custProductApply = new CustProductApply();

    CustProductApply custProductApplySelect =
        custProductApplyService.findNewApplyProduct(productId, custId);
    boolean isNull = null == custProductApplySelect;
    String flowNo =
        isNull
            ? Utility.nextCode(MerchantProductEnum.creditKak.name().toUpperCase())
            : custProductApplySelect.getFlowNo();
    custProductApply.setFlowNo(flowNo);
    custProductApply.setCustId(custId);
    custProductApply.setProductId(productId);
    if (!isNull) {
      custProductApply.setApplyId(custProductApplySelect.getApplyId());
    }
    custProductApply.setIsApply(true);
    custProductApply.setAuditTime(ConcurrentDateUtil.formatDateTime(new Date()));
    custProductApply
        .setCreditApplyTime(ConcurrentDateUtil.formatDateTime(ConcurrentDateUtil.addDayTime(new Date(), 30)));
    if (null == input) {
      custProductApply.setRejectMsg("");
      custProductApply.setSuggestion("");
      custProductApply.setCreditAmt(0);
      custProductApply.setCreditExpiretime("");
      custProductApply.setAuditResult(2);
      return custProductApply;
    }
    CreditKakDecisionResult creditResultDto =
        JacksonUtil.Json2Obj(JacksonUtil.Obj2Json(input),
            new TypeReference<CreditKakDecisionResult>() {});
    String status = creditResultDto.getAwardStatus();
    if (StringUtils.isNotEmpty(status)) {
      KakAuditResultEnum enumOnValue =
          EnumExtUtil.getEnumOnValue(KakAuditResultEnum.class, status, "key");
      switch (enumOnValue) {
        case applyFailed:
          custProductApply.setAuditResult(0);
          custProductApply.setCreditAmt(0);
          custProductApply.setCreditExpiretime("");
          custProductApply.setRejectMsg(KakAuditResultEnum.applyFailed.getDesc());
          break;
        case hasAmount:
          custProductApply
              .setCreditAmt((int) Double.parseDouble(creditResultDto.getCreditAmount()));
          custProductApply.setCreditExpiretime(Utility.getDateTimeString(creditResultDto
              .getExpireDate()));
          custProductApply.setCreditApplyTime("");
          custProductApply.setAuditResult(1);
          custProductApply.setRejectMsg("");
          custProductApply.setSuggestion("");
          break;
        case noneAmount:
          custProductApply.setAuditResult(0);
          custProductApply.setCreditAmt(0);
          custProductApply.setCreditExpiretime("");
          custProductApply.setRejectMsg(KakAuditResultEnum.noneAmount.getDesc());
          break;
        case withdrawFailed:
          custProductApply.setAuditResult(0);
          custProductApply.setCreditAmt(0);
          custProductApply.setCreditExpiretime("");
          custProductApply.setRejectMsg(KakAuditResultEnum.withdrawFailed.getDesc());
          break;
        case error:
          custProductApply.setAuditResult(0);
          custProductApply.setCreditAmt(0);
          custProductApply.setCreditExpiretime("");
          custProductApply.setRejectMsg(creditResultDto.getDescription());
          break;
        default:
          custProductApply.setAuditResult(0);
          custProductApply.setCreditAmt(0);
          custProductApply.setCreditExpiretime("");
          custProductApply.setRejectMsg("额度申请失败");
          break;
      }
    }

    return custProductApply;
  }

  /** 
   * TODO 简单描述该方法的实现功能（可选）. 
   * @see com.vcredit.creditcat.service.product.IProductApplyService#getProductCheckCreditParam(com.vcredit.creditcat.model.Cust) 
   */
  @Log
  @Override
  public Object getProductCheckCreditParam(Cust cust) {
    CreditKakAmountParamDto checkParamDto =
        new CreditKakAmountParamDto(
            Constants.PROJECT_PREFIX.concat(String.valueOf(cust.getCustId())),
            Constants.KAK_SUBMIT_ACCOUNT);
    return checkParamDto;
  }

  /** 
   * TODO 简单描述该方法的实现功能（可选）. 
   * @see com.vcredit.creditcat.service.product.IProductApplyService#checkCreditResult(java.lang.Object) 
   */
  @Log
  @Override
  public Object checkCreditResult(Long custId, Long productId, Object commitOutput) throws Exception {
    CommonResultExt<CreditKakDecisionResult> result =  JacksonUtil.Json2Obj(commitOutput.toString().replace(":\"\"", ":null"),
            new TypeReference<CommonResultExt<CreditKakDecisionResult>>() {});
    if (!"1".equals(result.getStatus())) {//失败
      return result.getMsg();
    }

    if ("02".equals(result.getData().getAwardStatus())) { //有额度保存
      creditCommonApplyService.saveCustProductApply(getSaveAuditResultParam(custId, productId,
          result.getData()));
      return null;
    }

    return "error";
  }
}
